﻿using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Xml.Linq;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using WidgetInterface;

/// <Summary>
/// Author: AustralTek 
/// Create date: 2010/05/04
/// http://www.australtek.com
/// Copyright: 2009 - 2010
/// </Summary>
namespace IndustrialDashboard
{
    public class DropDownPicker : IWidget
    {
        public List<Picker> pickerList { get; set; }
        private System.Web.Script.Serialization.JavaScriptSerializer jss = new System.Web.Script.Serialization.JavaScriptSerializer();
        public string message { get; set; }        
        private String strSource = "DropDownP.";
        public struct Picker
        {
            public Nullable<int> id;
            public string title;
            public string name;
            public Dictionary<string,string> typesList;
            public string legend;
            public int parentID;
            public Dictionary<String, Object> Attrib;
            public List<pickerOption> options;
        }
        public struct pickerOption
        {
            public Nullable<int> value;
            public string legend;
            public int defaultSelected;
            public Nullable<int> parentValue;
        }
        public DropDownPicker()
        {
            
            Logger.Info(strSource,"Initializing");
            pickerList = new List<Picker> { };
        }
        private List<pickerOption> fillPicker(DataTable dt)
        {
            try
            {
                List<pickerOption> aPickerOptions = new List<pickerOption> { };
                foreach (DataRow r in dt.Rows)
                {
                        pickerOption option = new pickerOption();
                        option.value = (Type.GetTypeCode(r.ItemArray[0].GetType()) == TypeCode.DBNull) ? (Nullable<int>)null : Convert.ToInt32(r.ItemArray[0]);
                        option.legend = r.ItemArray[1].ToString();
                        option.defaultSelected = Convert.ToInt32(r.ItemArray[2]);
                        option.parentValue = (Type.GetTypeCode(r.ItemArray[3].GetType()) == TypeCode.DBNull) ? (Nullable<int>)null : Convert.ToInt32(r.ItemArray[3]);

                        aPickerOptions.Add(option);
                }
                return aPickerOptions;
            }
            catch (IndexOutOfRangeException iore)
            {
                Logger.Warn(strSource,"Some data of the option's data is empty or null.", iore);
                Logger.Error(strSource, "Some data of the option's data is empty or null.", iore);
                throw new UserException("Some data of the option's data is empty or null.  Error: " + iore.Message);
            }
            catch (FormatException fe)
            {
                Logger.Warn(strSource, "Incorrect option's data format.",fe);
                Logger.Error(strSource, "Incorrect option's data format.", fe);
                throw new UserException("Incorrect option's data format.  Error: " + fe.Message);
            }
            catch (Exception ex)
            {
                Logger.Warn(strSource, "Problems building the picker's option.",ex);
                Logger.Error(strSource, "Problems building the picker's option.", ex);
                throw new Exception("Problems building the picker's option.  Error: " + ex.Message);
            }
        }
        public Dictionary<String, Object> ParseAttributes(String attributes)
        {
            try
            {
                Dictionary<String, Object> dic = new Dictionary<String, Object> { };
                if (attributes != "")
                {
                    attributes = attributes.Trim();

                    //JSON Expression
                    if ((attributes.StartsWith("{")) && (attributes.EndsWith("}")))
                    {
                        object obj = jss.DeserializeObject(attributes);

                        if ((typeof(System.Collections.Generic.Dictionary<string, object>) == obj.GetType()))
                        {
                            System.Collections.Generic.Dictionary<string, object> dObj = (System.Collections.Generic.Dictionary<string, object>)obj;
                            foreach (KeyValuePair<string, object> kvp in dObj)
                            {
                                try
                                {
                                    dic.Add(kvp.Key, kvp.Value);
                                }
                                catch (FormatException ex)
                                {
                                    Logger.Warn(strSource,"FormatException",ex);
                                    Logger.Error(strSource, "FormatException", ex);
                                    throw new UserException("Attribute: \"" + kvp.Key + "\", Value: \"" + kvp.Value + "\".  Error:" + ex.Message);
                                }
                            }
                        }
                    }
                    else//Simple Expression
                    {
                        String pattern = "^@+[a-zA-Z0-9._%+-]+:[a-zA-Z0-9._%+-<>='()|@]";
                        Regex myRegExp = new Regex(pattern);
                        if (myRegExp.IsMatch(attributes))
                        {
                            String[] Attrib = attributes.Split(',');
                            foreach (String s in Attrib)
                            {
                                try
                                {
                                    dic.Add(s.Split(':')[0].Replace("@", ""), s.Split(':')[1]);
                                }
                                catch (FormatException ex)
                                {
                                    Logger.Warn(strSource, "FormatException", ex);
                                    Logger.Error(strSource, "FormatException", ex);
                                    throw new UserException("Attribute: \"" + s + "\", Value: \"" + s.Split(':')[1] + "\".  Error:" + ex.Message); ;
                                }
                            }
                        }
                    }
                }
                return dic;
            }
            catch (Exception ex)
            {
                Logger.Warn(strSource, "Problems building the Picker's attributes", ex);
                Logger.Error(strSource, "Problems building the Picker's attributes", ex);
                throw new Exception("Problems building the Picker's attributes.  Error:" + ex.Message + " [Source: " + ex.Source + ". StackTrace: " + ex.StackTrace + "].;");
            }            
        }

        #region IWidget Members

        public object GenerateResponse(DataSet ds)
        {
            if (ds != null)
            {
                if (ds.Tables.Count > 0)
                {
                    if (ds.Tables[0].Rows.Count > 0)
                    {
                        try
                        {
                            System.Web.Script.Serialization.JavaScriptSerializer jss = new System.Web.Script.Serialization.JavaScriptSerializer();
                            foreach (DataRow r in ds.Tables[0].Rows)
                            {
                                Picker picker = new Picker();
                                picker.id = Convert.ToInt32(r["PickerID"]);
                                picker.title = r["Title"].ToString();
                                picker.name = r["Name"].ToString();
                                picker.typesList = jss.Deserialize<Dictionary<string,string>>(r["Type"].ToString());
                                picker.parentID = Convert.ToInt32(r["ParentID"]);
                                picker.Attrib = ParseAttributes(r["Attrib"].ToString());

                                int pickerID = Convert.ToInt32(r["PickerID"]);

                                if ((ds.Tables[pickerID] != null) && (ds.Tables[pickerID].Rows.Count > 0))
                                {
                                    try
                                    {
                                        picker.options = fillPicker(ds.Tables[pickerID]);
                                        pickerList.Add(picker);
                                    }
                                    catch (UserException ue)
                                    {
                                        Logger.Warn(strSource,"Problems building the picker's option.",ue);
                                        Logger.Error(strSource,"Problems building the picker's option.",ue);
                                        throw new UserException("Problems building the picker (ID: \"" + r["ParentID"] + "\").  Error: " + ue.Message);
                                    }
                                    catch (Exception ex)
                                    {
                                        Logger.Warn(strSource,"Problems building the picker's option.",ex);
                                        Logger.Error(strSource,"Problems building the picker's option.",ex);
                                        throw new Exception("Problems building the picker (ID: \"" + r["ParentID"] + "\").  Error: " + ex.Message);
                                    }
                                }
                                else
                                {
                                    Logger.Warn(strSource, "The picker's data tables (ID: " + r["ParentID"] + ") is null or empty]");                                   
                                    throw new UserException("The picker's data tables (ID: " + r["ParentID"] + ") is null or empty");
                                }
                            }
                        }
                        catch (FormatException fe)
                        {
                            Logger.Warn(strSource, "The meta data table is not formatted well", fe);
                            Logger.Error(strSource, "The meta data table is not formatted well", fe);
                            throw new UserException("The meta data table is not formatted well.  Error: " + fe.Message);
                        }
                        catch (ArgumentException ae)
                        {
                            Logger.Warn(strSource, "The meta data table data's format or the source table's format doesn't match with correct format of a Drop Down Picker's \"Data\" table", ae);
                            Logger.Error(strSource, "The meta data table data's format or the source table's format doesn't match with correct format of a Drop Down Picker's \"Data\" table", ae);
                            throw new UserException("The meta data table data's format or the source table's format doesn't match with correct format of a Drop Down Picker's \"Data\" table.  Error: " + ae.Message);
                        }
                    }
                    else
                    {
                        Logger.Warn(strSource, "The meta data table has no tables rows");
                        throw new UserException("The meta data table has no tables rows");
                    }
                }
                else
                {
                    Logger.Warn(strSource, "The dbo's data has no data tables");
                    throw new UserException("The dbo's data has no data tables");
                }
                return this;
            }
            else
            {
                Logger.Warn(strSource, "The data set is null");
                throw new UserException("The data set is null");
            }
        }

        public object GetExcelChunk(System.IO.Stream document)
        {
            Logger.Warn(strSource, "GetExcelChunk() [NotImplementedException]");
            throw new NotImplementedException();
            //return null;
        }

        public object GetPDFChunk(System.IO.Stream document)
        {
            Logger.Warn(strSource, "GetPDFChunk() [NotImplementedException]");
            throw new NotImplementedException();
            //return null;
        }

        #endregion
    }
}